package handler

import (
	"net/http"

	"database/sql"

	"gitee.com/hp-huiw/family-expense-api/internal/dto"
	"gitee.com/hp-huiw/family-expense-api/internal/service"
	"gitee.com/hp-huiw/my-go-core/util"
	"github.com/gin-gonic/gin"
)

type BankCardHandler interface {
	QueryAllWithBasicInfoByAccountGroup(ctx *gin.Context)
	QueryBasicInfoByAccountGroup(ctx *gin.Context)
	QueryBankCardInfo(ctx *gin.Context)
	Add(ctx *gin.Context)
	Update(ctx *gin.Context)
	Delete(ctx *gin.Context)
	BatchDelete(ctx *gin.Context)
}

func NewBankCardHandler(db *sql.DB) BankCardHandler {
	return &bankCardHandler{
		bankCardService: service.NewBankCardService(db),
	}
}

// Matches /query-all-with-basic-info-by-account-group of http get action.
func (h *bankCardHandler) QueryAllWithBasicInfoByAccountGroup(ctx *gin.Context) {
	c := ctx.Request.Context()
	claims := GetClaims(ctx)
	result, err := h.bankCardService.QueryAllWithBasicInfo(c, claims.AccountGroupID)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendDataResponse(ctx, result)
}

// Matches /query-basic-info-by-account-group of http get action.
func (h *bankCardHandler) QueryBasicInfoByAccountGroup(ctx *gin.Context) {
	pageSize, err := util.StringToInt64(ctx.Query("pageSize"))

	if err != nil {
		ctx.Error(err)
		return
	}

	pageIndex, err := util.StringToInt64(ctx.Query("pageIndex"))

	if err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	result, err := h.bankCardService.QueryBasicInfo(c, accountGroupID, pageSize, pageIndex)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendDataResponse(ctx, result)
}

// Matches /query-bank-card-info of http get action.
func (h *bankCardHandler) QueryBankCardInfo(ctx *gin.Context) {
	c := ctx.Request.Context()
	id := ctx.Query("id")
	accountGroupID := GetClaims(ctx).AccountGroupID
	result, err := h.bankCardService.QueryBankCardInfo(c, accountGroupID, id)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendDataResponse(ctx, result)
}

// Matches /add of http post action.
func (h *bankCardHandler) Add(ctx *gin.Context) {
	postedData := &dto.AddBankCardRequest{}

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	err := h.bankCardService.Add(c, accountGroupID, postedData)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendStatusResponse(ctx, http.StatusNoContent)
}

// Matches /update of http post action.
func (h *bankCardHandler) Update(ctx *gin.Context) {
	postedData := &dto.UpdateBankCardRequest{}

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	err := h.bankCardService.Update(c, accountGroupID, postedData)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendStatusResponse(ctx, http.StatusNoContent)
}

// Matches /delete of http post action.
func (h *bankCardHandler) Delete(ctx *gin.Context) {
	var postedData struct {
		ID string `json:"id"`
	}

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	result, err := h.bankCardService.Delete(c, accountGroupID, postedData.ID)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendDataResponse(ctx, result)
}

// Matches /batch-delete of http post action.
func (h *bankCardHandler) BatchDelete(ctx *gin.Context) {
	var postedData struct {
		IDs []string `json:"ids"`
	}

	if err := ctx.ShouldBindJSON(&postedData); err != nil {
		ctx.Error(err)
		return
	}

	c := ctx.Request.Context()
	accountGroupID := GetClaims(ctx).AccountGroupID
	err := h.bankCardService.BatchDelete(c, accountGroupID, postedData.IDs)

	if err != nil {
		ctx.Error(err)
		return
	}

	SendStatusResponse(ctx, http.StatusNoContent)
}

// Container of BankCardHandler functions.
type bankCardHandler struct {
	bankCardService service.BankCardService
}
